package com.janyee.powerdroid.glide

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Point
import android.os.Build
import android.renderscript.RSRuntimeException
import android.util.Log

import com.bumptech.glide.Glide
import com.bumptech.glide.load.Transformation
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
import com.bumptech.glide.load.resource.bitmap.BitmapResource

import jp.wasabeef.glide.transformations.internal.FastBlur
import jp.wasabeef.glide.transformations.internal.RSBlur

/**
 * Created by kmlixh on 2017/3/16.
 * useage:
 * TripManager
 */

class PartBlurTransformation(internal var mContext: Context, internal var mOrigenation: PartBlurTransformation.Origenation, internal var mRadius: Int, internal var degrees: Int) : Transformation<Bitmap> {
    internal var mBitmapPool: BitmapPool

    init {
        mBitmapPool = Glide.get(mContext).bitmapPool
    }

    override fun transform(resource: Resource<Bitmap>, outWidth: Int, outHeight: Int): Resource<Bitmap> {
        val source = resource.get()
        val width = source.width
        val height = source.height
        val scaledWidth: Int
        val scaledHeight: Int
        if (outHeight * width / outWidth <= width) {
            scaledWidth = outWidth
            scaledHeight = height * outWidth / width
        } else {
            scaledHeight = outHeight
            scaledWidth = width * outHeight / height
        }
        var bitmap: Bitmap? = mBitmapPool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888)
        if (bitmap == null) {
            bitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888)
        }
        val canvas = Canvas(bitmap!!)
        val paint = Paint()
        canvas.scale(scaledWidth / width.toFloat(), scaledHeight / height.toFloat(), 0f, 0f)
        paint.flags = Paint.FILTER_BITMAP_FLAG
        canvas.drawBitmap(source, 0f, 0f, paint)
        var cropBitmap = cropBitmap(bitmap, degrees, mOrigenation)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            try {
                cropBitmap = RSBlur.blur(mContext, cropBitmap, mRadius)
            } catch (e: RSRuntimeException) {
                cropBitmap = FastBlur.blur(cropBitmap, mRadius, true)
            }

        } else {
            cropBitmap = FastBlur.blur(cropBitmap, mRadius, true)
        }
        val cropCanvas = Canvas(bitmap)
        val start = getStart(degrees, mOrigenation, bitmap.width, bitmap.height)
        cropCanvas.drawBitmap(cropBitmap, start.x.toFloat(), start.y.toFloat(), paint)
        return BitmapResource.obtain(bitmap, mBitmapPool)
    }

    override fun getId(): String {
        return "PartBlurTransformation( )'"
    }

    enum class Origenation {
        Left, Right, Top, Bottom, Center, TopLeft, TopRight, BottomLeft, BottomRight
    }

    companion object {

        private fun cropBitmap(bitmap: Bitmap, degrees: Int, mOrigenation: Origenation): Bitmap {
            val start = getStart(degrees, mOrigenation, bitmap.width, bitmap.height)
            val size = getSize(degrees, mOrigenation, bitmap.width, bitmap.height)
            Log.e("====", "size:" + size.x + "|" + size.y + ",position:" + start.x + "|" + start.y + ",bitmap:" + bitmap.width + "|" + bitmap.height)
            return Bitmap.createBitmap(bitmap, start.x, start.y, size.x, size.y, null, false)
        }

        private fun getSize(degrees: Int, mOrigenation: Origenation, imageWidth: Int, imageHeight: Int): Point {
            val cropWidth: Int
            val cropHeight: Int
            when (mOrigenation) {
                PartBlurTransformation.Origenation.Center, PartBlurTransformation.Origenation.TopLeft, PartBlurTransformation.Origenation.TopRight, PartBlurTransformation.Origenation.BottomLeft, PartBlurTransformation.Origenation.BottomRight -> {
                    cropWidth = getLength(degrees, imageWidth)
                    cropHeight = getLength(degrees, imageHeight)
                }
                PartBlurTransformation.Origenation.Top, PartBlurTransformation.Origenation.Bottom -> {
                    cropWidth = imageWidth
                    cropHeight = getLength(degrees, imageHeight)
                }
                PartBlurTransformation.Origenation.Left, PartBlurTransformation.Origenation.Right -> {
                    cropWidth = getLength(degrees, imageWidth)
                    cropHeight = imageHeight
                }
                else -> {
                    cropWidth = getLength(degrees, imageWidth)
                    cropHeight = getLength(degrees, imageHeight)
                }
            }
            return Point(cropWidth, cropHeight)
        }

        private fun getStart(degrees: Int, mOrigenation: Origenation, imageWidth: Int, imageHeight: Int): Point {
            val x: Int
            val y: Int
            val cropWidth: Int
            val cropHeight: Int
            val size = getSize(degrees, mOrigenation, imageWidth, imageHeight)
            cropWidth = size.x
            cropHeight = size.y
            if (mOrigenation == null) {
                return Point(0, 0)
            } else {
                when (mOrigenation) {
                    PartBlurTransformation.Origenation.Center -> {
                        x = (imageWidth - cropWidth) / 2
                        y = (imageHeight - cropHeight) / 2
                    }
                    PartBlurTransformation.Origenation.Top -> {
                        x = (imageWidth - cropWidth) / 2
                        y = 0
                    }
                    PartBlurTransformation.Origenation.Bottom -> {
                        x = (imageWidth - cropWidth) / 2
                        y = imageHeight - cropHeight
                    }
                    PartBlurTransformation.Origenation.Left -> {
                        x = 0
                        y = (imageHeight - cropHeight) / 2
                    }
                    PartBlurTransformation.Origenation.Right -> {
                        x = imageWidth - cropWidth
                        y = (imageHeight - cropHeight) / 2
                    }
                    PartBlurTransformation.Origenation.TopLeft -> {
                        x = 0
                        y = 0
                    }
                    PartBlurTransformation.Origenation.TopRight -> {
                        x = imageWidth - cropWidth
                        y = 0
                    }
                    PartBlurTransformation.Origenation.BottomLeft -> {
                        x = 0
                        y = imageHeight - cropHeight
                    }
                    PartBlurTransformation.Origenation.BottomRight -> {
                        x = imageWidth - cropWidth
                        y = imageHeight - cropHeight
                    }
                    else -> {
                        x = (imageWidth - cropWidth) / 2
                        y = (imageHeight - cropHeight) / 2
                    }
                }
                return Point(x, y)
            }
        }

        fun getDegrees(length: Int, total: Int): Int {
            return length * 10000 / total
        }

        fun getLength(degrees: Int, total: Int): Int {
            return total * degrees / 10000
        }
    }
}
